package com.atguigu.gmall.cart.service;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.feign.GmallPmsClient;
import com.atguigu.gmall.cart.feign.GmallSmsClient;
import com.atguigu.gmall.cart.feign.GmallWmsClient;
import com.atguigu.gmall.cart.interceptor.LoginInterceptor;
import com.atguigu.gmall.cart.pojo.Cart;
import com.atguigu.gmall.cart.pojo.UserInfo;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.common.exception.CartException;
import com.atguigu.gmall.pms.entity.SkuAttrValueEntity;
import com.atguigu.gmall.pms.entity.SkuEntity;
import com.atguigu.gmall.sms.vo.ItemSaleVo;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class CartService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private AsyncCartService asyncCartService;
    @Autowired
    private GmallPmsClient pmsClient;
    @Autowired
    private GmallWmsClient wmsClient;
    @Autowired
    private GmallSmsClient smsClient;

    private static final String KEY_PREFIX = "cart:info:";
    private static final String PRICE_PREFIX = "cart:price:";

    //新增购物车
    public void addCart(Cart cart) {
        //获取登录状态
        String userId = getUserId();
        //获取当前用户的购物车,map<skuId,CartJson>
        BoundHashOperations<String, Object, Object> hashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userId);
        String skuId = cart.getSkuId().toString();
        //本次新增的数量
        BigDecimal count = cart.getCount();
        //判断当前用户的购物车是否包含该商品
        if (hashOps.hasKey(skuId)) {
            //包含-累加数量
            String json = hashOps.get(skuId).toString();
            cart = JSON.parseObject(json, Cart.class);
            cart.setCount(cart.getCount().add(count));
//            //重新写入数据库
//            hashOps.put(skuId,JSON.toJSONString(cart));

            //保存到数据库
            asyncCartService.updateCart(userId,cart,  skuId);

        }else {
            //不包含-新增记录

            //根据skuId查询sku
            ResponseVo<SkuEntity> skuEntityResponseVo = pmsClient.querySkuById(cart.getSkuId());
            SkuEntity skuEntity = skuEntityResponseVo.getData();
            if (skuEntity == null){
                throw new CartException("你加入购物车商品不存在");
            }
            cart.setUserId(userId);
            cart.setCheck(true);
            cart.setTitle(skuEntity.getTitle());
            cart.setDefaultImage(skuEntity.getDefaultImage());
            cart.setPrice(skuEntity.getPrice());

            //是否有货
            ResponseVo<List<WareSkuEntity>> wmsClientBySkuId = wmsClient.getBySkuId(cart.getSkuId());
            List<WareSkuEntity> wareSkuEntities = wmsClientBySkuId.getData();
            if (CollectionUtils.isNotEmpty(wareSkuEntities)){
                cart.setStore(wareSkuEntities.stream().anyMatch(
                        wareSkuEntity -> wareSkuEntity.getStock()-wareSkuEntity.getStockLocked()>0));
            }

            //销售属性
            ResponseVo<List<SkuAttrValueEntity>> listResponseVo = pmsClient.querySkuAttrValueBySKuId(cart.getSkuId());
            List<SkuAttrValueEntity> skuAttrValueEntities = listResponseVo.getData();
            cart.setSaleAttrs(JSON.toJSONString(skuAttrValueEntities));

            //营销信息
            ResponseVo<List<ItemSaleVo>> saleList = smsClient.querySalesBySkuId(cart.getSkuId());
            List<ItemSaleVo> saleListData = saleList.getData();
            cart.setSales(JSON.toJSONString(saleListData));

            //保存到数据库
            asyncCartService.insertCart(userId,cart);

            //添加实时价格缓存
            stringRedisTemplate.opsForValue().set(PRICE_PREFIX+skuId,skuEntity.getPrice().toString());

        }
        //保存到数据库
        hashOps.put(skuId,JSON.toJSONString(cart));




    }



    private static String getUserId() {
        //获取登录状态，登录-userId，未登录-userKey
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        String userId = userInfo.getUserKey();
        //如果userId不为空就用userId，否则就用userKey
        if (userInfo.getUserId() != null){
            userId = userInfo.getUserId().toString();
        }
        return userId;
    }

    //新增后回显
    public Cart queryCartBySkuId(Long skuId) {

        //获取登录状态
        String userId = getUserId();

        //获取内层map<SkuId,CartJson>
        BoundHashOperations<String, Object, Object> hashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userId);
        if (hashOps.hasKey(skuId.toString())){
            String json = hashOps.get(skuId.toString()).toString();
            return JSON.parseObject(json, Cart.class);
        }
        throw new CartException("你的购物车中不包含此商品");
    }

    public List<Cart> queryCarts() {
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        //根据userKey查询未登陆的购物车
        BoundHashOperations<String, Object, Object> unloginHashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userInfo.getUserKey());
        List<Object> unloginCartJsons = unloginHashOps.values();//未登录购物车的value
        List<Cart> unloginCarts = null;
        if (CollectionUtils.isNotEmpty(unloginCartJsons)){
            //将CartJson->Cart
            unloginCarts = unloginCartJsons.stream().map(
                    unloginCart -> {
                        Cart cart = JSON.parseObject(unloginCart.toString(), Cart.class);
                        //设置实时价格缓存
                        cart.setCurrentPrice(new BigDecimal(
                                stringRedisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId())));
                    return cart;
                    }).collect(Collectors.toList());
        }

        //获取userId判断登录状态，如果未登录直接返回未登录的购物车
        Long userId = userInfo.getUserId();
        if (userId == null){
            return unloginCarts;
        }

        
        //根据userId，获取已登录的购物车，把未登录的购物车合并到已登录的购物车中去
        BoundHashOperations<String, Object, Object> loginHashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userId);
        //遍历未登录购物车，合并到已登录的购物车中去
        if (CollectionUtils.isNotEmpty(unloginCarts)){
            unloginCarts.forEach(cart->{//未登录购物车对象
                String skuId = cart.getSkuId().toString();
                BigDecimal count = cart.getCount();
                if (loginHashOps.hasKey(skuId)){
                    //如果已登录的购物车中已经包含了该记录  数量累加
                    String json = loginHashOps.get(skuId).toString();
                    cart = JSON.parseObject(json, Cart.class);
                    cart.setCount(cart.getCount().add(count));
                    asyncCartService.updateCart(userId.toString(),cart,skuId);
                }else {
                    //如果已登录购物车不包含该记录，则新增
                    cart.setId(null);//id是主键自增的
                    cart.setUserId(userId.toString());
                    asyncCartService.insertCart(userId.toString(),cart);
                }
                loginHashOps.put(skuId,JSON.toJSONString(cart));

            });
        }


        //清空未登录的购物车
        asyncCartService.deleteCart(userInfo.getUserKey());
        stringRedisTemplate.delete(KEY_PREFIX + userInfo.getUserKey());

        //返回合并后的已登录的购物车展示给前端
        List<Object> loginHashOpsList = loginHashOps.values();
        if (CollectionUtils.isNotEmpty(loginHashOpsList)){
            //把json序列化成购物车对象展示给前端
            return loginHashOpsList.stream().map(
                    json->{
                        Cart cart = JSON.parseObject(json.toString(), Cart.class);
                        cart.setCurrentPrice(new BigDecimal(
                                stringRedisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId())));
                        return cart;
                    }).collect(Collectors.toList());
        }

        return null;
    }

    //更新购物车
    public void updateNum(Cart cart) {
        //获取登录状态
        String userId = getUserId();
        //获取购物车
        BoundHashOperations<String, Object, Object> hashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userId);
        String json = hashOps.get(cart.getSkuId().toString()).toString();
        //先获取要更新的数量
        BigDecimal count = cart.getCount();
        cart = JSON.parseObject(json, Cart.class);
        cart.setCount(count);
        //写入数据库
        asyncCartService.updateCart(userId,cart,cart.getSkuId().toString());
        hashOps.put(cart.getSkuId().toString(),JSON.toJSONString(cart));
    }

    //删除购物车
    public void deleteBySkuId(Long skuId) {
        String userId = getUserId();
        BoundHashOperations<String, Object, Object> boundHashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userId);
        boundHashOps.delete(skuId.toString());
        asyncCartService.deleteBySkuId(userId,skuId);
    }

    public List<Cart> queryCartByUserId(Long userId) {
        //TODO:根据userKey查询未登录的购物车，取消已登录状态的购物车中所有商品的选中状态，把未登录的购物车合并到已登录的购物车中去

        //根据UserId查询已选中的购物车
        BoundHashOperations<String, Object, Object> hashOps =
                stringRedisTemplate.boundHashOps(KEY_PREFIX + userId);
        List<Object> cartJsons = hashOps.values();
        if (CollectionUtils.isEmpty(cartJsons)){
            return null;
        }
        List<Cart> cartList =
                cartJsons.stream().map(cartJson -> JSON.parseObject(cartJson.toString(), Cart.class))
                .filter(cart -> cart.getCheck()).collect(Collectors.toList());
        return cartList;
    }
}
